﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace LooseChart
{
    /// <summary>
    /// 伪彩图
    /// </summary>
    public class PseudoColorSeries : XYSeries
    {
        public PseudoColorSeries() : base() { }

        /// <summary>
        /// 绘制内容
        /// </summary>
        /// <param name="color">基础颜色</param>
        /// <param name="list">矢量数据流</param>
        /// <param name="dc">画布</param>
        protected override void DrawDrawingContext(Color color, List<StreamGeometry> list, DrawingContext dc)
        {
            var pa = color.A / 255d;
            var count = list.Count;
            for (int i = 0; i < count; i++)
            {
                var stream = list[i];
                if (stream.IsEmpty()) continue;
                var c = GetGradientColor(i, count, color);
                var fillbrush = new SolidColorBrush(Color.FromArgb(Convert.ToByte(FillColorA * pa), c.R, c.G, c.B));
                fillbrush.Freeze();
                var strokebrush = new SolidColorBrush(Color.FromArgb(Convert.ToByte(StrokeColorA * pa), c.R, c.G, c.B));
                strokebrush.Freeze();
                Brush fill = ShowFill ? fillbrush : null;
                Pen pen = ShowStroke ? new Pen(strokebrush, StrokeThickness) { DashStyle = base.DashStyle } : null;
                dc.DrawGeometry(fill, pen, stream);
            }
        }

        /// <summary>
        /// 获取数据源的矢量数据流
        /// </summary>
        /// <param name="chartDataSource">数据源</param>
        /// <returns></returns>
        protected override async Task UpdateStreamGeometry(CancellationToken token)
        {
            if (!this.IsLoaded || token.IsCancellationRequested || XAxis == null || YAxis == null) return;
            var points = Statistics;
            if (points == null || points.Count <= 0)
            {
                MainGeometry = null;
                return;
            }
            var pointLength = PointLength;
            try
            {
                var temp = await Task.Factory.StartNew<List<StreamGeometry>>((Func<List<StreamGeometry>>)(() =>
                {
                    var maxcount = points.Max(p => p.Count);
                    var mincount = points.Min(p => p.Count);
                    var range = maxcount - mincount;
                    if (range <= 0) range = 1;
                    var countrange = range;
                    if (countrange > 768) countrange = 768;
                    List<StreamGeometry> streams = new List<StreamGeometry>(Convert.ToInt32(countrange));
                    Dictionary<int, StreamGeometryContext> contexts = new Dictionary<int, StreamGeometryContext>();
                    for (var j = 0; j <= countrange; j++)
                    {
                        StreamGeometry stream = new StreamGeometry();
                        streams.Add(stream);
                        contexts[j] = stream.Open();
                    }
                    foreach (var point in points)
                    {
                        if (token.IsCancellationRequested) return null;
                        if (point.Count < mincount || point.Count > maxcount) continue;
                        var index = Convert.ToInt32((point.Count - mincount) * countrange / range);
                        var sgc = contexts[index];
                        var otherpoints = new Point[]
                        {
                            new Point(point.Point.X + pointLength, point.Point.Y),
                            new Point(point.Point.X + pointLength, point.Point.Y + pointLength),
                            new Point(point.Point.X, point.Point.Y + pointLength)
                        };
                        sgc.BeginFigure(point.Point, true, true);
                        sgc.PolyLineTo(otherpoints, true, false);
                    }
                    foreach (var item in contexts) item.Value.Close();
                    streams.ForEach(p => p.Freeze());
                    return streams;
                }), token);
                if (!token.IsCancellationRequested) MainGeometry = temp;
            }
            catch (TaskCanceledException e)
            {
                Debug.WriteLine(string.Concat("伪彩图生成矢量图线程被取消", e));
            }
        }
    }
}
